﻿import ko = require("knockout")

const initialHandAngle = 40;

class KnobInintalizer {
    public constructor(params: IKnobParams) {
        this.value = params.value;
        this.min = ko.isObservable(params.min) ? params.min : ko.observable(params.min == null ? 0 : params.min);
        this.max = ko.isObservable(params.max) ? params.max : ko.observable(params.max == null ? 0 : params.max);
    }

    public value: KnockoutObservable<number>;

    public min: KnockoutObservable<number>;

    public max: KnockoutObservable<number>;
}

class Knob extends KnobInintalizer {
    public constructor(params: IKnobParams) {
        super(params);
    }

    public drag = (event, $data) => {
        event.stopPropagation();

        var newVal = this.value() + (event.translationY / 40);
        if (newVal > this.max()) newVal = this.max();
        if (newVal < this.min()) newVal = this.min();
        this.value(newVal);
    }

    public normalizedValue: KnockoutComputed<number> = ko.pureComputed({
        read: () => this.value() - this.min(),
        write: (value) => {
            this.value(ko.unwrap(value) + this.min());
        }
    });

    private valueRange = ko.pureComputed(() => this.max() - this.min());

    public percent = ko.pureComputed({
        read: () => this.normalizedValue() / this.valueRange(),
        write: (value) => this.normalizedValue(ko.unwrap(value) * this.valueRange())
    });

    public handAngle: KnockoutComputed<number> = ko.computed(() => {
        return (270 - initialHandAngle) - this.percent() * (360 - 2 * initialHandAngle);
    });

    public handTransform: KnockoutComputed<string> = ko.pureComputed((): string => {
        return ("rotate(" + (180 - this.handAngle()) + "deg)");
    });

    public radAngle: KnockoutComputed<number> = ko.pureComputed((): number => {
        return (this.handAngle()) * (Math.PI / 180);
    });

    public highlightPath: KnockoutComputed<string> = ko.pureComputed((): string => {
        return "M -29.57 35.24 A 46 46 0 " +
        ~~(this.handAngle() <= 90-initialHandAngle) +
        " 1 " + Math.cos(this.radAngle()) * 46 + " " + (-Math.sin(this.radAngle()) * 46);
    });
}

export = Knob 